package com.tre.jdevtemplateboot.aop;

import com.tre.jdevtemplateboot.annotatiaon.FileAuthorizationValidate;
import com.tre.jdevtemplateboot.common.authority.GateKeeper;
import com.tre.jdevtemplateboot.common.authority.TokenTakeApart;
import com.tre.jdevtemplateboot.common.dto.PropertiesConfig;
import com.tre.jdevtemplateboot.common.enums.AuthenticateTypeEnums;
import com.tre.jdevtemplateboot.common.redis.IDataBaseFileAuthorizationService;
import com.tre.jdevtemplateboot.common.redis.IRedisFileAuthorizationService;
import com.tre.jdevtemplateboot.common.util.BasedDesUtils;
import com.tre.jdevtemplateboot.exception.business.SysUnAuthorizedFileException;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author JDev
 */
@Aspect
@Component
@Order(4)
public class FileAuthorizationValidationAspect {

    @Autowired
    private IRedisFileAuthorizationService iRedisFileAuthorizationService;
    @Autowired(required = false)
    private IDataBaseFileAuthorizationService iDataBaseFileAuthorizationService;
    @Autowired
    private TokenTakeApart tokenTakeApart;
    @Autowired
    private PropertiesConfig propertiesConfig;
    @Autowired
    private GateKeeper gateKeeper;

    @Pointcut("@annotation(fileAuthorizationValidate)")
    public void pointcut(FileAuthorizationValidate fileAuthorizationValidate) {
        throw new UnsupportedOperationException();
    }

    @Before("pointcut(fileAuthorizationValidate)")
    public void doFileAuthorizationValidation(FileAuthorizationValidate fileAuthorizationValidate) {
        String reqHeaderUserId = tokenTakeApart.takeEncryptedUserId();
        String[] requiredPermissions = fileAuthorizationValidate.value();

        if (requiredPermissions != null && requiredPermissions.length > 0) {
            List<String> permissionList = null;
            if (AuthenticateTypeEnums.REDIS.toString().equalsIgnoreCase(propertiesConfig.getTokenCategory())) {
                permissionList = iRedisFileAuthorizationService.getRedisAuthorization(reqHeaderUserId);
            }
            if (permissionList == null) {
                permissionList = iDataBaseFileAuthorizationService.getDataBaseFileAuthorization(
                        BasedDesUtils.decryptBasedDes(reqHeaderUserId));
            }
            if (!gateKeeper.scan(permissionList).find(requiredPermissions).any()) {
                throw new SysUnAuthorizedFileException();
            }
            if (AuthenticateTypeEnums.REDIS.toString().equalsIgnoreCase(propertiesConfig.getTokenCategory())) {
                iRedisFileAuthorizationService.setRedisAuthorization(reqHeaderUserId,
                        String.join(",", permissionList));
            }
        }
    }
}
